#pragma once
#include <string>
#include "Space.h"
#include "Vector.h"
#include "SpaceAgent.h"
/*
  Copyright 2008 by Alexey Solovyev and University of Pittsburgh
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

namespace org
{
	namespace spark
	{
		namespace data
		{


			//using org::spark::math::Function;
			using org::spark::space::Space;
			using org::spark::space::SpaceAgent;
			using org::spark::math::Vector;

			/// <summary>
			/// The basic interface for representing a data layer.
			/// A data layer allows to specify numerical values at each point
			/// of a space. 
			/// </summary>
			class DataLayer 
			{

			public:
				virtual void setValue(int x, int y, double value) = 0;

				virtual double getValue(int x, int y) = 0;

				/// <summary>
				/// Sets the value of the data at the point x </summary>
				/// <param name="x"> a point </param>
				/// <param name="value"> a value </param>
				virtual void setValue(org::spark::math::Vector *x, double value) = 0;

				/// <summary>
				/// Sets the value of the data at each point </summary>
				/// <param name="value"> a value </param>
				virtual void setValue(double value) = 0;

				/// <summary>
				/// Sets the value of the data at the place occupied by the agent </summary>
				/// <param name="agent"> an agent </param>
				/// <param name="value"> a value </param>
				virtual void setValue(org::spark::space::SpaceAgent *agent, double value) = 0;


				/// <summary>
				/// Sets the value of the data at each point with respect
				/// to the values of the function f </summary>
				/// <param name="f"> a function </param>
				//virtual void setValue(org::spark::math::Function *f) = 0;


				/// <summary>
				/// Gets the value of the data at the point x </summary>
				/// <param name="x"> a point </param>
				/// <returns> value a value </returns>
				virtual double getValue(org::spark::math::Vector *x) = 0;

				/// <summary>
				/// Gets the value of the data at the place occupied by the agent </summary>
				/// <param name="agent"> an agent </param>
				/// <returns> value a value </returns>
				virtual double getValue(org::spark::space::SpaceAgent *agent) = 0;

				/// <summary>
				/// Adds the value to the data at the point x </summary>
				/// <param name="x"> a point </param>
				/// <param name="value"> a value </param>
				/// <returns> new value </returns>
				virtual double addValue(org::spark::math::Vector *x, double value) = 0;

				/// <summary>
				/// Adds the value to the data at the place occupied by the agent </summary>
				/// <param name="agent"> an agent </param>
				/// <param name="value"> a value </param>
				/// <returns> new value </returns>
				virtual double addValue(org::spark::space::SpaceAgent *agent, double value) = 0;

				/// <summary>
				/// Gets the vector at the point x which gives the direction
				/// of the gradient of the data </summary>
				/// <param name="x"> a point </param>
				/// <returns> gradient </returns>
				virtual org::spark::math::Vector *getGradient(org::spark::math::Vector *x) = 0;

				/// <summary>
				/// Gets a total number of data stored in the data layer </summary>
				/// <returns> a total number </returns>
				virtual double getTotalNumber() = 0;

				/// <summary>
				/// Do not call this method directly.
				/// It is used internally for processing the data layer
				/// </summary>
				virtual void process(long long tick) = 0;


				/// <summary>
				/// Called internally before processing agents
				/// Used for the implementation of the concurrent execution mode
				/// </summary>
				virtual void beginStep() = 0;

				/// <summary>
				/// Called internally after processing agents
				/// Used for the implementation of the concurrent execution mode
				/// </summary>
				virtual void endStep() = 0;


				/// <summary>
				/// Returns a space in which this data layer is defined
				/// @return
				/// </summary>
				virtual org::spark::space::Space *getSpace() = 0;
			};

		}
	}
}
